package com.itcam.maker.meta;

import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.json.JSONUtil;

/**
 * @author : Cammy.Wu
 * Description : 实现单例模式
 */

/**
 * 🌟 单例模式的MetaManager类，用于管理Meta对象的实例化
 * 如同一个严格的管家，确保整个系统中只有一个Meta对象实例。
 */
public class MetaManager {

    /**
     * 📦 私有静态变量，用于存储唯一的Meta对象实例
     * 使用volatile关键字确保多线程环境下的可见性，就像给这个变量安装了实时广播，让所有线程都能及时知晓它的状态。
     */
    private static volatile Meta meta;

    /**
     * 🚫 私有构造函数，防止外部实例化
     * 这就像给类的创建大门上了一把锁，外部无法通过常规的new操作来创建新实例，从而维护单例模式。
     */
    private MetaManager() {
        // 私有构造函数，防止外部实例化
    }

    /**
     * 👀 获取Meta对象的唯一实例
     * 如果实例尚未创建，则通过同步块创建实例
     * @return Meta对象的唯一实例
     */
    public static Meta getMetaObject() {
        // 🕵️ 第一次检查，避免不必要的同步
        // 就像先远远地看一眼宝藏（Meta对象）是否已经存在，避免无谓的靠近。
        if (meta == null) {
            // 🔒 同步块，确保只有一个线程可以创建实例
            // 好比给创建宝藏的房间加上了门禁，同一时间只有一个线程能进入。
            synchronized (MetaManager.class) {
                // 🕵️‍♂️ 第二次检查，确保实例尚未被其他线程创建
                // 进入房间后再确认一下宝藏是否真的没被其他线程先拿走。
                if (meta == null) {
                    // 🛠️ 调用initMeta方法初始化Meta对象
                    meta = initMeta();
                }
            }
        }
        // 🎁 返回Meta对象的唯一实例
        return meta;
    }

    /**
     * 🚀 初始化Meta对象
     *
     * @return 初始化后的Meta对象
     */
    private static Meta initMeta() {
        // 📖 从资源文件中读取meta.json的内容，并以UTF-8编码转换为字符串
        // 如同从知识宝库中取出一份珍贵的说明书。
        String metaJson = ResourceUtil.readUtf8Str("meta.json");
//        String metaJson = ResourceUtil.readUtf8Str("springboot-init-meta.json");

        // 🧙 将JSON字符串转换为Meta对象
        // 把说明书上的文字变成实际可用的工具。
        Meta newMeta = JSONUtil.toBean(metaJson, Meta.class);

        // 获取Meta对象中的FileConfig对象
        // Meta.FileConfig fileConfig = newMeta.getFileConfig();

        // ✅ 校验和处理默认值
        // 对工具进行检查和调试，确保它能正常使用。
        MetaValidator.doValidAndFill(newMeta);

        // 🎉 返回初始化后的Meta对象
        return newMeta;
    }

}

/*
    1.定义了meta属性，用于接受JSON配置。使用volatile关键字修饰，确保多线程环境下的可见性
    2.添加了一个私有构造函数，防止外部用new的方式创建出多个对象，破坏单例
    3.定义了getMetaObject方法，用于获取meta对象，如果是首次获取，则执行initMeta方法来初始化meta对象；否则直接获取已有对象。
        此处使用双重检测锁进行并发控制，即确保了对象获取性能不会被锁影响，也能防止重复实例化。
    4.定义了initMeta方法，用于从JSON文件中获取对象属性并初始化meta对象。当然后续还可以执行对象校验、填充默认值等操作
 */

